1   /*
2    * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  
24  /* @test
25   * @bug 4712786
26   * @summary Check charsets against reference files
27   *
28   * @build Util
29   * @run main Check shift_jis ref.shift_jis
30   * @run main/othervm -Dsun.nio.cs.map=Windows-31J/Shift_JIS Check shift_jis ref.windows-31j
31   */
32  
33  import java.io.*;
34  import java.nio.*;
35  import java.nio.channels.*;
36  import java.nio.charset.*;
37  import java.util.*;
38  import java.util.regex.*;
39  
40  
41  public class Check {
42  
43      private static PrintStream log = System.err;
44  
45      private static final int UNICODE_SIZE = (1 << 16);
46  
47      private final String csName;
48      private final String refName;
49      private byte[][] bytes = new byte[UNICODE_SIZE][]; // Indexed by char
50  
51      private int errors = 0;
52  
53      private Check(String csn, String refn) {
54          csName = csn;
55          refName = refn;
56      }
57  
58      private Check load()
59          throws IOException
60      {
61          File fn = new File(System.getProperty("test.src", "."), refName);
62          FileChannel fc = new FileInputStream(fn).getChannel();
63          ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
64          CharBuffer cb = Charset.forName("US-ASCII").decode(bb);
65          Pattern p = Pattern.compile("^(\\p{XDigit}+) +(\\p{XDigit}+)$",
66                                      Pattern.MULTILINE);
67          Matcher m = p.matcher(cb);
68          while (m.find()) {
69              char c = (char)Integer.parseInt(m.group(1), 16);
70              String v = m.group(2);
71              int nb = v.length() >> 1;
72              byte[] ba = new byte[nb];
73              for (int i = 0; i < nb; i++) {
74                  ba[i] = (byte)Integer.parseInt(v.substring(i << 1, (i << 1) + 2),
75                                                 16);
76              }
77              bytes[c] = ba;
78          }
79          return this;
80      }
81  
82      private void error() {
83          if (++errors >= 100)
84              throw new RuntimeException("100 errors occurred (there might be more)");
85      }
86  
87      private void mismatch(String s, byte[] expected, byte[] got) {
88          log.println("Encoding mismatch on \""
89                      + Util.toString(s)
90                      + "\": Expected {"
91                      + Util.toString(expected)
92                      + "}, got {"
93                      + Util.toString(got)
94                      + "}");
95          error();
96      }
97  
98      private void mismatch(int i, byte[] ba, String expected, String got) {
99          log.println("Decoding mismatch on \""
100                     + Util.toString((char)i)
101                     + "\", input {"
102                     + Util.toString(ba)
103                     + "}: Expected \""
104                     + Util.toString(expected)
105                     + "\", got \""
106                     + Util.toString(got)
107                     + "\"");
108         error();
109     }
110 
111     private void check()
112         throws IOException
113     {
114 
115         // String.getBytes(String csn)
116         for (int i = 0; i < UNICODE_SIZE; i++) {
117             if (bytes[i] == null)
118                 continue;
119             String s = new String(new char[]{ (char)i });
120             byte[] ba = s.getBytes(csName);
121             if (Util.cmp(ba, bytes[i]) >= 0)
122                 mismatch(s, bytes[i], ba);
123         }
124         log.println("String.getBytes(\"" + csName + "\") okay");
125 
126         // String(byte[] ba, String csn)
127         for (int i = 0; i < UNICODE_SIZE; i++) {
128             if (bytes[i] == null)
129                 continue;
130             String r = new String(new char[]{ (char)i });
131             String s = new String(bytes[i], csName);
132             if (!r.equals(s))
133                 mismatch(i, bytes[i], r, s);
134         }
135         log.println("String(byte[] ba, \"" + csName + "\") okay");
136 
137         // To be really thorough we should test OutputStreamWriter,
138         // InputStreamReader, and Charset{De,En}Coder here also,
139         // but the above will do for now.
140 
141         if (errors > 0) {
142             throw new RuntimeException(errors + " error(s) occurred");
143         }
144 
145     }
146 
147     // Usage: Check charsetName referenceFileName
148     public static void main(String[] args) throws Exception {
149         new Check(args[0], args[1]).load().check();
150     }
151 
152 }